<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <title>数字华容道</title>
    <script src="js/vue.js"></script>
</head>

<style type="text/css">
    * {
        padding: 0;
        margin: 0;
        box-sizing: border-box;
        list-style: none;
    }

    ul {
        width: 600px;
        height: 600px;
        display: flex;
        flex-wrap: wrap;
        margin: 30px auto;
    }

    li {
        width: 200px;
        height: 200px;
        background-image: url(img/bg.png);
        background-size: 600px;
        background-position: left top;
        border: 1px solid #fff;
    }

    .blank {
        background-image: none;
    }

    button {
        padding: 10px 20px;
        background: #421C0F;
        background-color: #421C0F;
        color: #fff;
        border-radius: 5px;
        display: block;
        margin: 10px auto;
    }

    #timer {
        text-align: center;
        font-size: 24px;
        margin-top: 20px;
        margin-bottom: 10px;
    }
</style>

<body>
    <div id='app'>
        <div id="timer">{{ formattedTime }}</div>
        <ul>
            <li v-for='(item, index) in imgs' 
			:style="{ backgroundPosition: item.pos }" 
			:class='!item.pos ? "blank" : ""'
            @click="move(index)">
            </li>
        </ul>
        <button @click="start">开始游戏</button>
    </div>
    <script type="text/javascript">
        Vue.createApp({
            data() {
                return {
                    imgs: [
                        { id: 1, pos: 'left top' },
                        { id: 2, pos: 'center top' },
                        { id: 3, pos: 'right top' },
                        { id: 4, pos: 'left center' },
                        { id: 5, pos: 'center' },
                        { id: 6, pos: 'right center' },
                        { id: 7, pos: 'left bottom' },
                        { id: 8, pos: 'center bottom' },
                        { id: 9, pos: '' }
                    ],
                    originalImgs: [],
                    time: 0,
                    timer: null
                };
            },
            computed: {
                formattedTime() {
                    const minutes = Math.floor(this.time / 60).toString().padStart(2, '0');
                    const seconds = (this.time % 60).toString().padStart(2, '0');
                    return `${minutes}:${seconds}`;
                }
            },
            methods: {
                start() {
                    // 停止之前的计时器
                    if (this.timer) {
                        clearInterval(this.timer);
                    }
                    // 重置时间
                    this.time = 0;
                    // 保存原始图片排列
                    this.originalImgs = [...this.imgs];
                    // 打乱图片顺序
                    this.shuffleImgs();
                    // 检查是否有解，如果无解则重新打乱
                    while (!this.isSolvable(this.imgs)) {
                        this.shuffleImgs();
                    }
                    // 启动计时器
                    this.timer = setInterval(() => {
                        this.time++;
                    }, 1000);
                },
                shuffleImgs() {
                    for (let i = this.imgs.length - 1; i > 0; i--) {
                        const j = Math.floor(Math.random() * (i + 1));
                        [this.imgs[i], this.imgs[j]] = [this.imgs[j], this.imgs[i]];
                    }
                },
                move(index) {
                    // 找到空白方块的索引
                    const blankIndex = this.imgs.findIndex(item => !item.pos);
                    // 上下左右的相邻方块索引
                    const neb = [index - 3, index + 3, index - 1, index + 1];
                    // 检查是否存在右边方块
                    if (Math.floor(index / 3) !== Math.floor(neb[3] / 3)) {
                        neb[3] = -1;
                    }
                    // 检查是否存在左边方块
                    if (Math.floor(index / 3) !== Math.floor(neb[2] / 3)) {
                        neb[2] = -1;
                    }
                    // 检查相邻方块是否为空白方块
                    for (let j = 0; j < neb.length; j++) {
                        if (neb[j] === blankIndex) {
                            // 交换当前方块和空白方块的位置
                            [this.imgs[index], this.imgs[blankIndex]] = [this.imgs[blankIndex], this.imgs[index]];
                            // 检查是否完成游戏
                            if (this.isGameOver()) {
                                // 停止计时器
                                clearInterval(this.timer);
                                alert(`恭喜你，游戏完成！用时：${this.formattedTime}`);
                            }
                            break;
                        }
                    }
                },
                isSolvable(arr) {
                    // 计算逆序数
                    let inversions = 0;
                    const len = arr.length;
                    for (let i = 0; i < len; i++) {
                        for (let j = i + 1; j < len; j++) {
                            if (arr[i].pos && arr[j].pos && arr[i].id > arr[j].id) {
                                inversions++;
                            }
                        }
                    }
                    // 对于 3x3 的数字华容道，逆序数为偶数则有解
                    return inversions % 2 === 0;
                },
                isGameOver() {
                    return this.imgs.every((item, index) => item.id === this.originalImgs[index].id);
                }
            }
        }).mount('#app');
    </script>
</body>

</html>